package com.wiki4j.gdo;

import java.util.HashMap;
import java.util.Map;

import com.wiki4j.gdo.type.GDTypeBase;
import com.wiki4j.gdo.type.GDTypeBigDecimal;
import com.wiki4j.gdo.type.GDTypeBoolean;
import com.wiki4j.gdo.type.GDTypeDouble;
import com.wiki4j.gdo.type.GDTypeInt;
import com.wiki4j.gdo.type.GDTypeLong;
import com.wiki4j.gdo.type.GDTypeString;

public class GDTypes{
  public static final String GDO_NS="gdo";
  public static final GDTypeBase TYPE_STRING=new GDTypeString();
  public static final GDTypeBase TYPE_INT=new GDTypeInt();
  public static final GDTypeBase TYPE_LONG=new GDTypeLong();
  public static final GDTypeBase TYPE_DOUBLE=new GDTypeDouble();
  public static final GDTypeBase TYPE_DECIMAL=new GDTypeBigDecimal();
  public static final GDTypeBase TYPE_BOOLEANL=new GDTypeBoolean();
  private static Map<String,Map<String,GDType>> types=new HashMap<String,Map<String,GDType>>();
  static{
    loadBasicType(GDTypeString.class);
    loadBasicType(GDTypeInt.class);
    loadBasicType(GDTypeLong.class);
    loadBasicType(GDTypeDouble.class);
    loadBasicType(GDTypeBigDecimal.class);
    loadBasicType(GDTypeBoolean.class);
  }

  private static void loadBasicType(Class<?> clazz){
    try{
      GDType type=(GDType)clazz.newInstance();
      putType(type);
    }catch(Exception e){
      throw new IllegalStateException("Fail to load basic type!");
    }
  }

  private static void putType(GDType type){
    String ns=type.namespace();
    String name=type.name();
    Map<String,GDType> nss=types.get(ns);
    if(nss==null) synchronized(types){
      nss=types.get(ns);
      if(nss==null){
        nss=new HashMap<String,GDType>();
        types.put(ns,nss);
      }
    }
    nss.put(name,type);
  }

  public static void registerType(GDType type){
    String ns=type.namespace();
    if(GDO_NS.equals(ns)) throw new IllegalArgumentException("Could not define basic(gdo) type");
    putType(type);
  }

  public static GDType getType(String ns,String name){
    Map<String,GDType> nss=types.get(ns);
    if(nss==null) return null;
    return nss.get(name);
  }

  public static GDType getType(String fullName){
    int indexOf=fullName.lastIndexOf('.');
    String ns=fullName.substring(0,indexOf);
    String name=fullName.substring(indexOf+1);
    return getType(ns,name);
  }
}
